/*
 * Copyright (c) 2025 DuckDuckGo
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.duckduckgo.lint.ui

import com.android.tools.lint.client.api.UElementHandler
import com.android.tools.lint.detector.api.Category.Companion.CUSTOM_LINT_CHECKS
import com.android.tools.lint.detector.api.Detector
import com.android.tools.lint.detector.api.Implementation
import com.android.tools.lint.detector.api.Issue
import com.android.tools.lint.detector.api.JavaContext
import com.android.tools.lint.detector.api.Scope
import com.android.tools.lint.detector.api.Severity
import com.android.tools.lint.detector.api.SourceCodeScanner
import com.android.tools.lint.detector.api.TextFormat
import org.jetbrains.uast.UCallExpression
import org.jetbrains.uast.getContainingUClass
import java.util.EnumSet

@Suppress("UnstableApiUsage")
class NoSetContentDetector : Detector(), SourceCodeScanner {

    override fun getApplicableUastTypes() = listOf(UCallExpression::class.java)

    override fun createUastHandler(context: JavaContext): UElementHandler = SetContentCallHandler(context)

    internal class SetContentCallHandler(private val context: JavaContext) : UElementHandler() {
        override fun visitCallExpression(node: UCallExpression) {
            if (isInDesignSystemModule(context.project.name)) return
            if (node.methodName == "setContent") {
                val containingClass = node.getContainingUClass()
                if (containingClass != null && isActivityClass(containingClass)) {
                    reportSetContentUsage(node)
                }
            }
        }

        private fun isActivityClass(cls: org.jetbrains.uast.UClass): Boolean {
            return context.evaluator.extendsClass(cls, "android.app.Activity", false)
        }

        private fun reportSetContentUsage(node: UCallExpression) {
            context.report(
                issue = NO_SET_CONTENT_USAGE,
                location = context.getLocation(node),
                message = NO_SET_CONTENT_USAGE.getExplanation(TextFormat.RAW)
            )
        }

        private fun isInDesignSystemModule(projectName: String): Boolean {
            return projectName.contains("design-system")
        }
    }

    companion object {
        val NO_SET_CONTENT_USAGE = Issue
            .create(
                id = "NoSetContentUsage",
                briefDescription = "setContent should not be used in Activities",
                explanation = "Compose is not yet approved to be used in production. The setContent function should not be used in Activities until Compose usage is officially approved for the codebase.",
                moreInfo = "https://app.asana.com/0/1202857801505092/list",
                category = CUSTOM_LINT_CHECKS,
                priority = 10,
                severity = Severity.ERROR,
                androidSpecific = true,
                implementation = Implementation(
                    NoSetContentDetector::class.java,
                    EnumSet.of(Scope.JAVA_FILE, Scope.TEST_SOURCES)
                )
            )
    }
}